//
//  GameHUD.m
//  Cocos2D Build a Tower Defense Game
//
//  Created by iPhoneGameTutorials on 4/4/11.
//  Copyright 2011 iPhoneGameTutorial.com All rights reserved.
//

#import "GameHUD.h"
#import "DataModel.h"
#import "Box2D.h"
#import "GLES-Render.h"
#import "PhysicsSprite.h"
#import "SimpleAudioEngine.h"
#define PTM_RATIO 32

#define k_y_space (44 + 20)


enum {
	kTagParentNode = 1,
};


@interface GameHUD()
{
    b2Body* mGroundBody;
    b2World* world;                     // strong ref
    GLESDebugDraw *m_debugDraw;		// strong ref
    CCTexture2D *spriteTexture_;	// weak ref
    PhysicsSprite *mSelSprite;
    NSArray *files;
}

@end

   

@implementation GameHUD

static GameHUD *_sharedHUD = nil;

+ (GameHUD *)sharedHUD
{
	@synchronized([GameHUD class])
	{
		if (!_sharedHUD)
			[[self alloc] init];
		return _sharedHUD;
	}
	// to avoid compiler warning
	return nil;
}

+(id)alloc
{
	@synchronized([GameHUD class])
	{
		NSAssert(_sharedHUD == nil, @"Attempted to allocate a second instance of a singleton.");
		_sharedHUD = [super alloc];
		return _sharedHUD;
	}
	// to avoid compiler warning
	return nil;
}

-(id) init
{
	if ((self=[super init]) ) {
		
        files = [[NSArray alloc] initWithObjects:@"banyuan.png",@"changfangxing.png",
                 @"zhengfangxing.png",@"sanjiao.png",@"tingxing.png",@"yuan.png",@"yuanzhu.png",
                 @"banyuan.png",nil];
      
        
		CGSize winSize = [CCDirector sharedDirector].winSize;

        [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565];
        background = [CCSprite spriteWithFile:@"hud.png"];
        background.opacity = 80;
        background.anchorPoint = ccp(0,1);
        //background.scale = 2;
        background.position = ccp(0,winSize.height- k_y_space);
        [self addChild:background];
        [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_Default];
		
        movableSprites = [[NSMutableArray alloc] init];
        /*
        NSArray *images = [NSArray arrayWithObjects:@"MachineGunTurret.png", @"MachineGunTurret.png", @"MachineGunTurret.png", @"MachineGunTurret.png", nil];       
        for(int i = 0; i < images.count; ++i) {
            NSString *image = [images objectAtIndex:i];
            CCSprite *sprite = [CCSprite spriteWithFile:image];
            float offsetFraction = ((float)(i+1))/(images.count+1);
            sprite.position = ccp(winSize.width*offsetFraction, winSize.height - 22);
            sprite.scale = 2;
            [self addChild:sprite];
            [movableSprites addObject:sprite];
        }
         */
        //[self initPhysics];
        
#if 1
		// Use batch node. Faster
		//CCSpriteBatchNode *parent = [CCSpriteBatchNode batchNodeWithFile:@"blocks.png" capacity:100];
		//spriteTexture_ = [parent texture];
#else
		// doesn't use batch node. Slower
		spriteTexture_ = [[CCTextureCache sharedTextureCache] addImage:@"blocks.png"];
		CCNode *parent = [CCNode node];
#endif
		//[self addChild:parent z:0 tag:kTagParentNode];
        
		[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
        
        [self scheduleUpdate];
        
        [self schedule: @selector(myTimer) interval: 2];
	}
	return self;
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {  
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    //CGPoint touchLocationInGameLayer = [self convertTouchToNodeSpace:touchLocation];
    
    //[self addNewSpriteAtPosition:touchLocation];
    
    CCSprite * newSprite = nil;
    DataModel *m = [DataModel getModel];
    for(CCSprite *sprite in m._blocks)
    {
        if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
			//DataModel *m = [DataModel getModel];
			m._gestureRecognizer.enabled = NO;
			
			selSpriteRange = [CCSprite spriteWithFile:@"Range.png"];
			selSpriteRange.scale = 2;
			[self addChild:selSpriteRange z:-1];
			selSpriteRange.position = sprite.position;
			
            mSelSprite = sprite;
            newSprite = [CCSprite spriteWithTexture:[sprite texture]]; //sprite;
			newSprite.position = sprite.position;
			selSprite = newSprite;
			[self addChild:newSprite];
            [[SimpleAudioEngine sharedEngine] playEffect:@"choose.wav"];
			
            break;
        }
    }
    
    /*
    for (CCSprite *sprite in movableSprites) {
        if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {  
			DataModel *m = [DataModel getModel];
			m._gestureRecognizer.enabled = NO;
			
			selSpriteRange = [CCSprite spriteWithFile:@"Range.png"];
			selSpriteRange.scale = 4;
			[self addChild:selSpriteRange z:-1];
			selSpriteRange.position = sprite.position;
			
            newSprite = [CCSprite spriteWithTexture:[sprite texture]]; //sprite;
			newSprite.position = sprite.position;
			selSprite = newSprite;
			[self addChild:newSprite];
			
            break;
        }
    }
    */
	return YES;
}

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {  
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    
    CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
    oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
    oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
    
    CGPoint translation = ccpSub(touchLocation, oldTouchLocation);    
	
	if (selSprite) {
		CGPoint newPos = ccpAdd(selSprite.position, translation);
        selSprite.position = newPos;
		selSpriteRange.position = newPos;
		
		//DataModel *m = [DataModel getModel];
		//CGPoint touchLocationInGameLayer = [m._gameLayer convertTouchToNodeSpace:touch];
		
		BOOL isBuildable =YES; //[m._gameLayer canBuildOnTilePosition: touchLocationInGameLayer];
		if (isBuildable) {
			selSprite.opacity = 200;
		} else {
			selSprite.opacity = 50;		
		}
	}
}

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {  
	CGPoint touchLocation = [self convertTouchToNodeSpace:touch];	
	DataModel *m = [DataModel getModel];

	if (selSprite) {
		CGRect backgroundRect = CGRectMake(background.position.x, 
									   background.position.y, 
									   background.contentSize.width, 
									   background.contentSize.height);
		
		if (!CGRectContainsPoint(backgroundRect, touchLocation)) {
			CGPoint touchLocationInGameLayer = [m._gameLayer convertTouchToNodeSpace:touch];
           
            //world->DestroyBody([mSelSprite getPhysicsBody]);
            [m._blocks removeObject:mSelSprite];
            //[self removeChild:mSelSprite cleanup:YES];
            //CCNode *parent = [self getChildByTag:kTagParentNode];
            //[parent removeChild:mSelSprite cleanup:YES];
            [self removeChild:mSelSprite cleanup:YES];
            
            /*
            for(PhysicsSprite *sprite in m._targets)
            {
                b2Body *body = [sprite getPhysicsBody];
                b2Vec2 v;
                v.Set(-1.0f, 0.0f);
                body->SetLinearVelocity(v);
            }
             */
            //[mSelSprite  release];
            
            mSelSprite = nil;
			[m._gameLayer addTower: touchLocationInGameLayer];
		}
		
		[self removeChild:selSprite cleanup:YES];
		selSprite = nil;		
		[self removeChild:selSpriteRange cleanup:YES];
		selSpriteRange = nil;			
	}
	
	m._gestureRecognizer.enabled = YES;
}
- (void) registerWithTouchDispatcher
{
	[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}


-(void) initPhysics
{
	
	CGSize s = [[CCDirector sharedDirector] winSize];
	
	b2Vec2 gravity;
	gravity.Set(0.0f, 0.0f);
	world = new b2World(gravity);
	
	
    //world->SetGravity(<#const b2Vec2 &gravity#>)
	// Do we want to let bodies sleep?
	world->SetAllowSleeping(true);
	
	world->SetContinuousPhysics(true);
	
	m_debugDraw = new GLESDebugDraw( PTM_RATIO );
	world->SetDebugDraw(m_debugDraw);
	
	uint32 flags = 0;
	flags += b2Draw::e_shapeBit;
	//		flags += b2Draw::e_jointBit;
	//		flags += b2Draw::e_aabbBit;
	//		flags += b2Draw::e_pairBit;
	//		flags += b2Draw::e_centerOfMassBit;
	m_debugDraw->SetFlags(flags);
	
    float ySpace =32;
    float y = s.height - k_y_space - ySpace;
	// Define the ground body.

	b2BodyDef groundBodyDef;

	groundBodyDef.position.Set(0, 0); // bottom-left corner
	
	// Call the body factory which allocates memory for the ground body
	// from a pool and creates the ground box shape (also from a pool).
	// The body is also added to the world.
	mGroundBody = world->CreateBody(&groundBodyDef);
	
	// Define the ground box shape.
	b2EdgeShape groundBox;
	

    
    float height = ySpace + y;
    //float height = 70;
    
    
    // bottom
	groundBox.Set(b2Vec2(0,y/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,y/PTM_RATIO));
	mGroundBody->CreateFixture(&groundBox,0);
    
    // top
	groundBox.Set(b2Vec2(0,height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,(height)/PTM_RATIO));
	mGroundBody->CreateFixture(&groundBox,0);
    
	
	
	
	
	// left
	groundBox.Set(b2Vec2(0,height/PTM_RATIO), b2Vec2(0,y/PTM_RATIO));
	mGroundBody->CreateFixture(&groundBox,0);
	
	// right
	groundBox.Set(b2Vec2(s.width/PTM_RATIO,height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,y/PTM_RATIO));
	mGroundBody->CreateFixture(&groundBox,0);
}


-(void)addNewSpriteByPosition:(CGPoint)p
{
    CCNode *parent = [self getChildByTag:kTagParentNode];
	
	//We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
	//just randomly picking one of the images
	int idx = (CCRANDOM_0_1() > .5 ? 0:1);
	int idy = (CCRANDOM_0_1() > .5 ? 0:1);
    CCSprite *sprite = [CCSprite spriteWithTexture:spriteTexture_ rect:CGRectMake(32 * idx,32 * idy,32,32)];
    
    DataModel *m = [DataModel getModel];
    [m._blocks addObject:sprite];
	[parent addChild:sprite];
	
	sprite.position = ccp(p.x, p.y);
}


-(void) addNewSpriteAtPosition:(CGPoint)p
{
	CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);
	CCNode *parent = [self getChildByTag:kTagParentNode];
	
	//We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
	//just randomly picking one of the images
	int idx = (CCRANDOM_0_1() > .5 ? 0:1);
	int idy = (CCRANDOM_0_1() > .5 ? 0:1);
	PhysicsSprite *sprite = [PhysicsSprite spriteWithTexture:spriteTexture_ rect:CGRectMake(32 * idx,32 * idy,32,32)];
    DataModel *m = [DataModel getModel];
    [m._targets addObject:sprite];
	[parent addChild:sprite];
	
	sprite.position = ccp( p.x, p.y);
	
	// Define the dynamic body.
	//Set up a 1m squared box in the physics world
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;
	bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
	b2Body *body = world->CreateBody(&bodyDef);
    b2Vec2 v;
    v.Set(-2.0f, 0.0f);
    body->SetLinearVelocity(v);
	
	// Define another box shape for our dynamic body.
	b2PolygonShape dynamicBox;
	dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
	
	// Define the dynamic body fixture.
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &dynamicBox;
	fixtureDef.density = 10.0f;
	//fixtureDef.friction = 1.0f;
	body->CreateFixture(&fixtureDef);
	
	[sprite setPhysicsBody:body];
}


-(void)myTimer
{
    //CCLOG(@"myTimer");
    /*
    CGSize s = [[CCDirector sharedDirector] winSize];
    CGPoint p;
    p.x = s.width - 16;
    p.y = s.height - 16 - k_y_space;
    DataModel *m = [DataModel getModel];
    if(m._targets.count > 1)
    {
        //PhysicsSprite *sprite2 = [m._targets objectAtIndex:m._targets.count - 2];
        PhysicsSprite *sprite = [m._targets objectAtIndex:m._targets.count - 1];
        
        //int x2 = sprite2.position.x;
        int x1 = sprite.position.x;
        int w = x1 + 32;
        CCLOG(@"w = %d",w);
        
        if( w >= s.width)
        {
            return;
        }
    }
    [self addNewSpriteAtPosition:p];
     */
    
    int rand = CCRANDOM_0_1() * 7;
    NSString *file = [files objectAtIndex:rand];
    CCSprite *sprite =[CCSprite spriteWithFile:file];
    //sprite.scale = 0.5;
    
    CGSize s = [[CCDirector sharedDirector] winSize];
    CGPoint p;
    p.x = s.width - sprite.textureRect.size.width/2;
    p.y = s.height -  sprite.textureRect.size.height/2 - k_y_space;
    DataModel *m = [DataModel getModel];
    if(m._blocks.count > 1)
    {
        //PhysicsSprite *sprite2 = [m._targets objectAtIndex:m._targets.count - 2];
        CCSprite *sprite = [m._blocks objectAtIndex:m._blocks.count - 1];
        
        //int x2 = sprite2.position.x;
        int x1 = sprite.position.x + sprite.textureRect.size.width/2;
        int w = x1 + sprite.textureRect.size.width;
        CCLOG(@"w = %d",w);
        
        if( w >= s.width)
        {
            return;
        }
    }
    
    [m._blocks addObject:sprite];
    [self addChild:sprite];
	sprite.position = ccp(p.x, p.y);
}

/*
-(void) update: (ccTime) dt
{
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/
	
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
	
	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	world->Step(dt, velocityIterations, positionIterations);
}
 */

// convenience method to convert a CGPoint to a b2Vec2
-(b2Vec2) toMeters:(CGPoint)point
{
	return b2Vec2(point.x / PTM_RATIO, point.y / PTM_RATIO);
}

// convenience method to convert a b2Vec2 to a CGPoint
-(CGPoint) toPixels:(b2Vec2)vec
{
	return ccpMult(CGPointMake(vec.x, vec.y), PTM_RATIO);
}
-(void) update: (ccTime) dt
{
    DataModel *m = [DataModel getModel];
    for( int i = 0; i < m._blocks.count; i++)
    {
        CCSprite *sprint = [m._blocks objectAtIndex:i];
        CGPoint p;
        p.x = 0.5;
        p.y = 0;
        CGPoint newPos = ccpSub(sprint.position, p);
        int w = sprint.textureRect.size.width/2;
        if(newPos.x <= w)
        {
            newPos.x = w;
        }
        BOOL move = YES;
        if(i>=1)
        {
            CCSprite *sprint1 = [m._blocks objectAtIndex:i-1];
            int w1 = sprint1.textureRect.size.width/2;
            if((sprint1.position.x + w1 + w) > sprint.position.x)
            {
                move = NO;
                 //newPos = ccpAdd(sprint.position, p);
            }
        }
        if(move)
        {
            sprint.position = newPos;
        }
        
    }
    /*
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/
	
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
	
	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	world->Step(dt, velocityIterations, positionIterations);
    
    // for each body, get its assigned sprite and update the sprite's position
	for (b2Body* body = world->GetBodyList(); body != nil; body = body->GetNext())
	{
		CCSprite* sprite = (CCSprite*)body->GetUserData();
		if (sprite != NULL)
		{
			// update the sprite's position to where their physics bodies are
			sprite.position = [self toPixels:body->GetPosition()];
			float angle = body->GetAngle();
			sprite.rotation = CC_RADIANS_TO_DEGREES(angle) * -1;
		}
	}
     */
}

/*
-(void) draw
{
	//
	// IMPORTANT:
	// This is only for debug purposes
	// It is recommend to disable it
	//
	[super draw];
	
	ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
	
	kmGLPushMatrix();
	
	world->DrawDebugData();
	
	kmGLPopMatrix();
}
*/

// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	[movableSprites release];
    movableSprites = nil;
    [files release];
    files = nil;
	[super dealloc];
}
@end
